package com.atguigu.crowd.mvc.config;


import com.atguigu.crowd.constant.CrowdConstant;
import com.atguigu.crowd.exception.AccessForbiddenException;
import com.atguigu.crowd.exception.LoginAcctAlreadyInUseException;
import com.atguigu.crowd.exception.LoginAcctAlreadyInUseForUpdateException;
import com.atguigu.crowd.exception.LoginFailedException;
import com.atguigu.crowd.until.CrowdUtil;
import com.atguigu.crowd.until.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@ControllerAdvice
public class CrowdExceptionResolver {

    @ExceptionHandler(value = LoginAcctAlreadyInUseForUpdateException.class)
    public ModelAndView resolveAccessForbiddenException(LoginAcctAlreadyInUseForUpdateException loginAcctAlreadyInUseForUpdateException,
                                                        HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 账号重复则刷新页面
        String viewName = "system-error";
        return commonResolve(viewName, request, response, loginAcctAlreadyInUseForUpdateException);

    }

    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolveAccessForbiddenException(LoginAcctAlreadyInUseException loginAcctAlreadyInUseException,
                                                        HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 账号重复则刷新页面
        String viewName = "admin-add";
        return commonResolve(viewName, request, response, loginAcctAlreadyInUseException);

    }

    @ExceptionHandler(value = Exception.class)
    public ModelAndView resolveAccessForbiddenException(Exception exception,
                                                        HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 如果未登录则直接返回登录页
        String viewName = "system-error";
        return commonResolve(viewName, request, response, exception);

    }

    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveArithmeticException(LoginFailedException loginFailedException, HttpServletRequest request,
                                                   HttpServletResponse response) throws IOException {

        //如果抛出登陆失败异常则直接返回登录页
        String viewName = "admin-login";
        return commonResolve(viewName, request, response, loginFailedException);
    }

    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(NullPointerException exception, HttpServletRequest request,
                                                    HttpServletResponse response) throws IOException {

        String viewName = "system-error";
        return commonResolve(viewName, request, response,exception);
    }


    /**
     * 将上面的公共部分提取出来，上面的异常处理只需要调下面的方法即可
     * @param viewName
     * @param request
     * @param response
     * @param exception
     * @return
     * @throws IOException
     */
    private ModelAndView commonResolve(String viewName, HttpServletRequest request,
                                       HttpServletResponse response, Exception exception) throws IOException {

        //判断是否为ajax请求
        boolean judgeResult = CrowdUtil.judgeRequestType(request);

        //如果是ajax请求
        if(judgeResult){
            //将异常信息发送给ResultEntity对象
            ResultEntity<Object> failed = ResultEntity.failed(exception.getMessage());

            //将ResultEntity对象转换为JSON字符串
            Gson gson = new Gson();
            String json = gson.toJson(failed);

            //将JSON字符串作为响应体返回给浏览器
            response.getWriter().write(json);

            return null;
        }

        //如果不是ajax请求，则直接返回一个页面
        ModelAndView modelAndView = new ModelAndView();
        //将Exception对象存入模型
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);
        //设置对应的视图
        modelAndView.setViewName(viewName);
        return modelAndView;
    }

}
